package common

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"serialnet/model"
	"strings"
	"sync"
	"time"
)

type Logger struct {
	enable bool
	save   bool
	filter model.LogType
	file   *os.File
	path   string
	date   string
	logger *log.Logger
	mutex  *sync.Mutex
}

func NewLogger(enable bool, save bool, filter model.LogType) *Logger {
	if filter > model.Debug || filter < model.Error {
		panic("filter invalid")
	}
	return &Logger{enable: enable, save: save, filter: filter, mutex: &sync.Mutex{}}
}

func (l *Logger) Enable() {
	l.enable = true
}
func (l *Logger) Disable() {
	l.enable = false
}

func (l *Logger) Debug(msg ...interface{}) {
	if !l.enable {
		return
	}
	if byte(l.filter) < byte(model.Debug) {
		return
	}
	l.mutex.Lock()
	defer l.mutex.Unlock()
	if l.save {
		l.saveToFile(model.Debug, msg)
	}
	pc, file, line, _ := runtime.Caller(1) // 0 -3 四级调用层级
	pcName := runtime.FuncForPC(pc).Name() // 获取方法名称
	temp := strings.Split(file, "/")
	file = temp[len(temp)-1]
	temp = strings.Split(pcName, ".")
	method := temp[len(temp)-1]
	fmt.Println("Debug—>", time.Now().Format("15:04:05.000"), "[", file, ",", method, ",", line, ",]", "—>", msg)
}
func (l *Logger) Info(msg ...interface{}) {
	if !l.enable {
		return
	}
	if byte(l.filter) < byte(model.Info) {
		return
	}
	l.mutex.Lock()
	defer l.mutex.Unlock()
	if l.save {
		l.saveToFile(model.Info, msg)
	}

	pc, file, line, _ := runtime.Caller(1) // 0 -3 四级调用层级
	pcName := runtime.FuncForPC(pc).Name() // 获取方法名称
	temp := strings.Split(file, "/")
	file = temp[len(temp)-1]
	temp = strings.Split(pcName, ".")
	method := temp[len(temp)-1]
	fmt.Println("Info—>", time.Now().Format("15:04:05.000"), "[", file, ",", method, ",", line, ",]", "—>", msg)
	//fmt.Println("Info——>", time.Now().Format("15:04:05.000"), "—>", message)

}
func (l *Logger) Warn(msg ...interface{}) {
	if !l.enable {
		return
	}
	if byte(l.filter) < byte(model.Warn) {
		return
	}
	l.mutex.Lock()
	defer l.mutex.Unlock()
	if l.save {
		l.saveToFile(model.Warn, msg)
	}
	pc, file, line, _ := runtime.Caller(1) // 0 -3 四级调用层级
	pcName := runtime.FuncForPC(pc).Name() // 获取方法名称
	temp := strings.Split(file, "/")
	file = temp[len(temp)-1]
	temp = strings.Split(pcName, ".")
	method := temp[len(temp)-1]
	fmt.Println("Warn—>", time.Now().Format("15:04:05.000"), "[", file, ",", method, ",", line, ",]", "—>", msg)
}
func (l *Logger) Error(msg ...interface{}) {
	if !l.enable {
		return
	}
	if byte(l.filter) < byte(model.Error) {
		return
	}
	l.mutex.Lock()
	defer l.mutex.Unlock()
	if l.save {
		l.saveToFile(model.Error, msg)
	}
	pc, file, line, _ := runtime.Caller(1) // 0 -3 四级调用层级
	pcName := runtime.FuncForPC(pc).Name() // 获取方法名称
	temp := strings.Split(file, "/")
	file = temp[len(temp)-1]
	temp = strings.Split(pcName, ".")
	method := temp[len(temp)-1]
	fmt.Println("Error—>", time.Now().Format("15:04:05.000"), "[", file, ",", method, ",", line, ",]", "—>", msg)
	//fmt.Println("Error——>", time.Now().Format("15:04:05.000"), "—>", message)
}

func (l *Logger) saveToFile(logType model.LogType, msg ...interface{}) {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("日志组件出错:", err)
		}
	}()
	d := time.Now().Format("20060102")
	if l.date != d {
		if l.file != nil {
			_ = l.file.Close()
			l.file = nil
			l.logger = nil
		}
		l.date = d
		l.path = GetLogPath() + l.date + ".log"
		f, err := os.OpenFile(l.path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0444)
		if err == nil {
			l.file = f
			l.logger = log.New(f, "", log.Ltime|log.Lmicroseconds)
		}
	}
	if l.logger != nil {
		if byte(l.filter) < byte(logType) {
			return
		}
		pc, file, line, _ := runtime.Caller(2) // 0 -3 四级调用层级
		pcName := runtime.FuncForPC(pc).Name() // 获取方法名称
		temp := strings.Split(file, "/")
		file = temp[len(temp)-1]
		temp = strings.Split(pcName, ".")
		method := temp[len(temp)-1]
		switch logType {
		case model.Debug:
			l.logger.SetPrefix(fmt.Sprintf("Debug—>%s [%s,%s,%d]—>", time.Now().Format("15:04:05.000"), file, method, line))
		case model.Info:
			l.logger.SetPrefix(fmt.Sprintf("Info—>%s [%s,%s,%d]—>", time.Now().Format("15:04:05.000"), file, method, line))
		case model.Warn:
			l.logger.SetPrefix(fmt.Sprintf("Warn—>%s [%s,%s,%d]—>", time.Now().Format("15:04:05.000"), file, method, line))
		case model.Error:
			l.logger.SetPrefix(fmt.Sprintf("Error—>%s [%s,%s,%d]—>", time.Now().Format("15:04:05.000"), file, method, line))
		}
		l.logger.Println(msg)
	}
}
